//
// SoapTrace.Net - A soap message monitoring utility. 
//
// Copyright (C) 2004-2007 Matthew Ward
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Matthew Ward (mrward@users.sourceforge.net)

using SoapTrace.Core.Formatters;
using System;
using System.IO;
using NUnit.Framework;

namespace SoapTrace.Tests
{
	/// <summary>
	/// Tests the <see cref="SoapMessageFormatterConfig"/> class.
	/// </summary>
	[ TestFixture ]
	public class SoapFormatterConfigTestFixture
	{
		/// <summary>
		/// Tests the loading of a web service configuration that contains
		/// parameters and return values that are arrays.
		/// </summary>
		[ Test ]
		public void WebServiceWithArrays( )
		{
			StringReader Reader = new StringReader( GetConfigXml( ) );
			SoapMessageFormatterConfig Config = SoapMessageFormatterConfig.Load( Reader );
			
			// Check the read in values.
			
			Assert.AreEqual( 1, Config.WebServices.Count, "Incorrect number of web services" );
			
			WebService WebService = Config.WebServices[ 0 ];
			
			Assert.AreEqual( "Test", WebService.Name, "Incorrect web service name." );
			Assert.AreEqual( "Test.asmx", WebService.Uri, "Incorrect web service uri." );
			
			// Test the web service operations.
			Assert.AreEqual( 1, WebService.Operations.Count, "Incorrect number of web service operations." );
			
			WebServiceOperation Operation = WebService.Operations[ 0 ];
			
			Assert.AreEqual( 3, Operation.Parameters.Count, "Incorrect number of parameters." );
		
			// Test the parameters.
			CheckParam( Operation.Parameters[ 0 ], "string.array", "param1", true );
			CheckParam( Operation.Parameters[ 1 ], "string.array", "param2", true );
			CheckParam( Operation.Parameters[ 2 ], "string", "param3", true );
			
			Assert.AreEqual( true, Operation.Parameters[ 0 ].IsArray, "Parameter should be an array." );
			Assert.AreEqual( "string", Operation.Parameters[ 0 ].ArrayType, "Array type is incorrect." );
			
			Assert.AreEqual( true, Operation.Parameters[ 1 ].IsArray, "Parameter should be an array." );
			Assert.AreEqual( "string", Operation.Parameters[ 1 ].ArrayType, "Array type is incorrect." );

			Assert.AreEqual( false, Operation.Parameters[ 2 ].IsArray, "Parameter should not be an array." );
			Assert.AreEqual( "", Operation.Parameters[ 2 ].ArrayType, "Array type is incorrect." );

			// Test the parameter arrays.
			Assert.AreEqual( 1, Operation.Parameters[ 0 ].Items.Count, "Incorrect parameter array item count." );
			CheckArrayItem( Operation.Parameters[ 0 ].Items[ 0 ], "string", "item", false );

			Assert.AreEqual( 0, Operation.Parameters[ 1 ].Items.Count, "Incorrect parameter array item count." );
			Assert.AreEqual( 0, Operation.Parameters[ 2 ].Items.Count, "Incorrect parameter array item count." );
			
			// Test the return value.
			CheckReturnValue( Operation.ReturnValue, "xml.array", "result", true );
			
			Assert.AreEqual( true, Operation.ReturnValue.IsArray, "Should be an array." );
			Assert.AreEqual( "xml", Operation.ReturnValue.ArrayType, "Array type is incorrect." );
		
			Assert.AreEqual( 2, Operation.ReturnValue.Items.Count, "Incorrect return value array item count." );
			CheckArrayItem( Operation.ReturnValue.Items[ 0 ], "xml", "result1", false );
			CheckArrayItem( Operation.ReturnValue.Items[ 1 ], "xml", "result2", true );
		}
		
		/// <summary>
		/// Tests the config is read correctly for a web service with
		/// no arrays. 
		/// </summary>
		[ Test ]
		public void WebServiceWithoutArrays( )
		{
			StringReader Reader = new StringReader( GetNonArrayConfigXml( ) );
			SoapMessageFormatterConfig Config = SoapMessageFormatterConfig.Load( Reader );
			
			// Check the read in values.
			
			Assert.AreEqual( 1, Config.WebServices.Count, "Incorrect number of web services" );
			
			WebService WebService = Config.WebServices[ 0 ];
			
			Assert.AreEqual( "TextEJB", WebService.Name, "Incorrect web service name." );
			Assert.AreEqual( "/TextEJB.asmx", WebService.Uri, "Incorrect web service uri." );
			
			// Test the web service operations.
			Assert.AreEqual( 1, WebService.Operations.Count, "Incorrect number of web service operations." );
			
			WebServiceOperation Operation = WebService.Operations[ 0 ];
			
			Assert.AreEqual( 1, Operation.Parameters.Count, "Incorrect number of parameters." );
		
			// Test the parameters.
			CheckParam( Operation.Parameters[ 0 ], "string", "string", true );
			
			Assert.AreEqual( false, Operation.Parameters[ 0 ].IsArray, "Parameter should not be an array." );
						
			// Test the return value.
			CheckReturnValue( Operation.ReturnValue, "compressedXml", "result", true );
			
			Assert.AreEqual( false, Operation.ReturnValue.IsArray, "Should not be an array." );
		}
		
		/// <summary>
		/// Gets the config xml for a web service with arrays to be used 
		/// in this test fixture.  
		/// </summary>
		/// <returns>The config xml.</returns>
		/// <remarks><para>The web service  represented by the xml has the 
		/// form:</para>
		/// <para>
		/// <code>string[] Test(string[] param1, string[] param2, string param3)</code>
		/// </para>
		/// </remarks>
		private string GetConfigXml( )
		{
			return "<soapmessageformatter.config xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
				"<webservice name='Test' uri='Test.asmx'>" +
				"	<operation name='getTest'>" +
				"		<params>" +
				"			<param type='string.array' name='param1' display='true'>" +
				"				<item type='string' name='item' display='false'/>" +
				"			</param>" +
				"			<param type='string.array' name='param2' display='true'/>" +
				"			<param type='string' name='param3' display='true'/>" +			
				"		</params>" +
				"		<returnValue type='xml.array' name='result' display='true'>" +
				"			<item type='xml' name='result1' display='false'/>" +
				"			<item type='xml' name='result2' display='true'/>" +
				"		</returnValue>	" +
				"	</operation>" +
				"</webservice>" +
				"</soapmessageformatter.config>	";
		}
		
		/// <summary>
		/// Gets the config xml for a web service with arrays to be used 
		/// in this test fixture.  
		/// </summary>
		/// <returns>The config xml.</returns>
		/// <remarks><para>The web service  represented by the xml has the 
		/// form:</para>
		/// <para>
		/// <code>string Compress(string string)</code>
		/// </para>
		/// </remarks>
		private string GetNonArrayConfigXml( )
		{
			return "<soapmessageformatter.config xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n" +
				"  <webservice name=\"TextEJB\" uri=\"/TextEJB.asmx\">\r\n" +
				"    <operation name=\"Compress\">\r\n" +
				"      <params>\r\n" +
				"        <param type=\"string\" name=\"string\" display=\"true\" />\r\n" +
				"      </params>\r\n" +
				"      <returnValues />\r\n" +
				"      <returnValue type=\"compressedXml\" name=\"result\" display=\"true\" />\r\n" +
				"    </operation>\r\n" +
				"  </webservice>\r\n" +
				"</soapmessageformatter.config>";
		}
		
		/// <summary>
		/// Checks that the <see cref="WebServiceParameter"/> contains the
		/// expected values.
		/// </summary>
		/// <param name="param">The parameter to test.</param>
		/// <param name="paramType">The expected parameter type.</param>
		/// <param name="name">The expected parameter name.</param>
		/// <param name="display">The expected display flag.</param>
		private void CheckParam( WebServiceParameter param, 
		                        string paramType,
		                        string name,
		                        bool display )
		{
			Assert.AreEqual( paramType, param.ParameterType, "Param type is incorrect." );
			Assert.AreEqual( name, param.Name, "Param name is incorrect." );
			Assert.AreEqual( display, param.Display, "Param name is incorrect." );			
		}
		
		/// <summary>
		/// Checks that the <see cref="WebServiceReturnValue"/> contains the
		/// expected values.
		/// </summary>
		/// <param name="returnValue">The return value to test.</param>
		/// <param name="returnValueType">The expected return value type.</param>
		/// <param name="name">The expected return value name.</param>
		/// <param name="display">The expected display flag.</param>
		private void CheckReturnValue( WebServiceReturnValue returnValue, 
		                        string returnValueType,
		                        string name,
		                        bool display )
		{
			Assert.AreEqual( returnValueType, returnValue.ParameterType, "Return value type is incorrect." );
			Assert.AreEqual( name, returnValue.Name, "Return value name is incorrect." );
			Assert.AreEqual( display, returnValue.Display, "Return value name is incorrect." );			
		}	
		
		/// <summary>
		/// Checks that the <see cref="WebServiceArrayItem"/> contains the
		/// expected values.
		/// </summary>
		/// <param name="arrayItem">The array item to test.</param>
		/// <param name="arrayItemType">The expected array item type.</param>
		/// <param name="name">The expected array item name.</param>
		/// <param name="display">The expected display flag.</param>
		private void CheckArrayItem( WebServiceArrayItem arrayItem, 
		                        string arrayItemType,
		                        string name,
		                        bool display )
		{
			Assert.AreEqual( arrayItemType, arrayItem.ItemType, "Array item type is incorrect." );
			Assert.AreEqual( name, arrayItem.Name, "Array item name is incorrect." );
			Assert.AreEqual( display, arrayItem.Display, "Array item name is incorrect." );			
		}		
	}
}
